home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
askrunlevel
/
askrunlevel.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-03
|
10KB
|
332 lines
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include "askrunlevel.h"
#include "internal.h"
#include <ncurses/curses.h>
#include "../misc/misc.h"
#include "../xconf/xconf.h"
#include "../netconf/netconf.h"
#include "../userconf/userconf.h"
#include "../main/main.h"
#include "../fstab/fstab.h"
#include "../paths.h"
#include "askrunlevel.m"
static HELP_FILE help_askrun (HELP_ASKRUN,"intro");
static HELP_FILE help_boot (HELP_ASKRUN,"boot");
/* #Specification: askrunlevel / intro
When linux boot, it start /sbin/init which does some
basic initialisation, then try to jump to its default
run level. If this default run level is not defined and
/sbin/askrunlevel do exist, then it is execute.
The purpose of this program is to let the user select the
run level in a meaningful way. Instead of numbers, it
present a menu of configuration useful for a workstation.
Also, askrunlevel try to validate which configuration are
possible. There is no need to ask the user if he want to
start X automatically (using xdm) unless X has been configured.
To make it easy for the user, askrunlevel act also has a first
time configuration utility. So if a configuration do not exist
it let the user configure it right away. No need to boot twice
(once to configure, and once to activate the configuration).
If the user do not select anything in a specific time, the
default run level is activate.
The future will tell if this is true...
*/
static void askrunlevel_saynographic(const char *status_graphic)
{
xconf_error (MSG_U(E_GRAPH,"Can't do this\n"
"because the Graphic mode is not yet\n"
"configured\n\n%s"),status_graphic);
}
static void askrunlevel_saynographic_net(
char *status_graphic,
char *status_net)
{
xconf_error (MSG_U(E_GRAPHNET,"Can't do this\n"
"because the Graphic mode\n"
"and the Networking are not yet\n"
"configured\n\n%s\n\n%s"),status_graphic,status_net);
}
static void askrunlevel_saynonet(char *status_net)
{
xconf_error (MSG_U(E_NET,"Can't do this\n"
"because the Networking is not yet\n"
"configured\n\n%s"),status_net);
}
/*
Activate the timeout only if the system is freshly start.
If uptime is old enough, it means askrunlevel was called
after the user explicitly told init to do so, so the timeout
feature is not useful here.
Return the timeout value (in seconds) or 0.
*/
static int askrunlevel_enabletimeout(ASK_PARM &parm)
{
FILE *fin = xconf_fopen ("/proc/uptime","r");
int timeout = 0;
// We assume that if /proc/uptime is not available, better
// play safe and disable the timeout feature.
if (fin != NULL){
/* #Specification: askrunlevel / automatic booting / timeout
linuxconf will automaticly boot the system into
the default runlevel (as configured) only
if it is called at boot time (when called as /sbin/askrunlevel).
There is two possibilities: Either the boot
was normal (ie. fairly fast) or fairly slow
(the system had to do a fsck after a crash).
In the first case, it will boot as configured
after the specified timeout.
If the system took more than 60 seconds to boot
it will still boot by itself, but will selected
a timeout of one minute. The system will
also activate the bell.
This is to catch the attention of the
operator.
*/
long uptime;
if (fscanf (fin,"%ld",&uptime)==1){
timeout = parm.timeout;
if(uptime > 60 && timeout != 0){
timeout = 60;
for (int i=0; i<2; i++){
putchar ('\a');
fflush (stdout);
sleep(1);
}
}
dialog_settimeout (timeout,MENU_ESCAPE,false);
}else{
xconf_error (MSG_U(E_PROCUPTIME,"Can't parse /proc/uptime\n"));
}
fclose (fin);
}
return timeout;
}
/*
Configure the default runlevel.
*/
void askrunlevel_config()
{
char status_graphic[2000];
int graphic_ok = xconf_xok(status_graphic);
char status_net[2000];
int net_ok = netconf_netok(status_net) != NULL;
int choice = 0;
while (1){
RUNLEVELS runlevels (graphic_ok,net_ok);
static const char *lilo_conf = MSG_U(M_LILO,"LILO (Linux boot loader)");
static const char *lilo_default = MSG_U(M_DEFLILO,"default boot configuration");
static const char *lilo_confaddany = MSG_U(M_NEWKERN,"a new kernel");
static const char *lilo_confaddcompil = MSG_U(M_COMPILED,"a kernel you have compiled");
static const char *config_mode = MSG_U(M_DEFBOOT,"default boot mode");
static const char *config_define = MSG_U(M_RUNLEVELS,"runlevels");
static const char *menuopt[]={
MSG_U(M_CONFIG,"Configure"), lilo_conf,
MSG_U(M_CHANGE,"Change"), lilo_default,
MSG_U(M_ADDLILO,"Add to LILO"), lilo_confaddany,
" ", lilo_confaddcompil,
"-", "",
" ", config_mode,
MSG_U(M_DEFINE,"Define"), config_define,
NULL
};
MENU_STATUS code = xconf_menu (
MSG_U(T_BOOTCONF,"Boot configuration")
,MSG_U(I_BOOTCONF,"You are allowed to define the default\n"
"boot mode of this computer")
,help_boot
,menuopt,choice);
if (code != MENU_OK){
break;
}else{
const char *key = menuopt[choice*2+1];
if (key == config_mode){
runlevels.config();
}else if (key == lilo_conf){
lilo_edit();
}else if (key == lilo_default){
lilo_setdefault();
}else if (key == lilo_confaddany){
lilo_addany();
}else if (key == lilo_confaddcompil){
lilo_addcompil();
}else if(key == config_define){
runlevels.define();
}
}
}
}
static int askrunlevel_chkterm ()
{
int ret = -1;
const char *pt = getenv ("TERM");
if (pt != NULL){
char path[PATH_MAX];
sprintf (path,"/usr/lib/terminfo/%c/%s",*pt,pt);
if (file_exist (path)) ret = 0;
}
return ret;
}
static void askrunlevel_setterm()
{
/* #Specification: askrunlevel / terminal type
askrunlevel is called very early at boot time. At this
time the TERM environnement variable is set directly by
the kernel (it can be overriden by init I think). In
kernel 1.2.x, it is generally set to "con80x25". In newer
kernel, it is set to "linux".
Many (Most) system out there simply do not have a
definition in /usr/lib/terminfo for such a TERM type.
When starting askrunlevel, we check if the TERM variable
do point to something in /usr/lib/terminfo. If not, TERM
is silently set to "linux". If linux is not defined, it
is set to "console". This should cover most cases.
*/
if (askrunlevel_chkterm()==-1){
putenv ("TERM=linux");
if (askrunlevel_chkterm()==-1){
putenv ("TERM=console");
if (askrunlevel_chkterm()==-1){
RUNLEVELS runlevels(0,0);
runlevels.setlevel (4);
printf (MSG_U(E_TERMINFO
,"No valid TERM definition\n"
"probably caused by an improperly installed\n"
"terminfo database.\n"));
exit (-1);
}
}
}
}
int askrunlevel_main (int , char *[])
{
modules_dummy(); // Just to ease the link
askrunlevel_setterm();
/* Specification: askrunlevel / principal
The user must select one of these choice
Start in graphic mode
graphic mode and network
text mode
text mode and network
maintenance mode
Set the default boot mode
Set the timeout value
*/
ASK_PARM parm;
boot_save2log();
/* Specification: askrunlevel / time & cmos
askrunlevel grab the time from cmos right at boot
time. The /sbin/clock command in most /etc/rc.d/rc.S
is useless.
*/
datetime_getfromcmos();
modules_check();
dialog_settimeout (15,MENU_ESCAPE,true);
fstab_check(); // Check /etc/fstab
fstab_checkmount(1); // mount local filesystems
configf_booterase(); // some cleanup
fixperm_check_boot(); // check some permissions
askrunlevel_readparm (parm);
dialog_settimeout (0,MENU_ESCAPE,false);
// Conditionnally activate the timeout
// firsttime toggle the message about the timeout
int timeout = askrunlevel_enabletimeout (parm);
int choice = parm.defmode;
while (1){
static const char *set_config = MSG_U(M_TWORKSTATION,"the workstation");
static const char *boot_log = MSG_U(M_BOOTLOGS,"the boot logs");
static const char *menuopt[]={
MSG_U(M_START,"Start"), NULL,
" ", NULL,
" ", NULL,
" ", NULL,
" ", NULL,
" ", NULL,
MSG_R(M_CONFIG), set_config,
MSG_U(M_VIEW,"View"), boot_log,
NULL
};
char status_graphic[2000];
int graphic_ok = xconf_xok(status_graphic);
char status_net[2000];
int net_ok = netconf_netok(status_net) != NULL;
RUNLEVELS runlevels (graphic_ok,net_ok);
runlevels.setmenu (menuopt);
char infohelp[500];
strcpy (infohelp,MSG_U(I_SELONE
,"Select one of the operation mode below\n"
"or configure the default mode"));
if (timeout != 0){
sprintf (infohelp+strlen(infohelp)
,MSG_U(I_WARN,"\n"
"Unless you select something within %d seconds\n"
"\"%s\" will start automaticly")
,timeout,menuopt[choice*2+1]);
}
timeout = 0;
MENU_STATUS code = xconf_menu (MSG_U(T_OPERMODE,"Operation mode")
,infohelp
,help_askrun
,menuopt,choice);
if (code != MENU_OK){
runlevels.setlevel(parm.defmode);
break;
}else{
const char *key = menuopt[choice*2+1];
if (key == set_config){
if (perm_checkpass()){
linuxconf_main(1);
askrunlevel_readparm (parm);
}
}else if (key == boot_log){
boot_showlog();
}else{
RUNLEVEL *ptrun = runlevels.tbrun + choice;
if (!ptrun->graphic_err && !ptrun->net_err){
if (ptrun->init_runlevel != 'S'
|| perm_checkpass()){
runlevels.setlevel(choice);
break;
}
}else if (ptrun->graphic_err
&& ptrun->net_err){
askrunlevel_saynographic_net(status_graphic,status_net);
}else if (ptrun->graphic_err){
askrunlevel_saynographic(status_graphic);
}else{
askrunlevel_saynonet(status_net);
}
}
}
}
return 0;
}